from dashscope.audio.tts_v2 import SpeechSynthesizer
import os
import re

from dotenv import load_dotenv
from moviepy.audio.io.AudioFileClip import AudioFileClip
from pydub import AudioSegment

load_dotenv()

def format_time(seconds):
    hours, remainder = divmod(seconds, 3600)
    minutes, seconds = divmod(remainder, 60)
    milliseconds = int((seconds - int(seconds)) * 1000)
    seconds = int(seconds)
    return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d},{milliseconds:03d}"


# 定义一个函数来获取音频文件的时长
def get_audio_duration(file_path):
    audio = AudioFileClip(file_path)
    duration = audio.duration
    audio.close()
    return duration


# 定义一个函数来生成SRT格式的字幕行
def create_srt_line(index, start_time, end_time, text):
    return f"{index}\n{start_time} --> {end_time}\n{text}\n\n"


# def generate_srt_from_audio(base_dir: str, output_dir: str, output_srt_file: str) -> None:
#     """
#     从指定目录下的音频文件夹生成SRT字幕文件。
#
#     :param base_dir: 包含音频文件夹的根目录。
#     :param output_dir: 输出SRT文件的目录。
#     :param output_srt_file: 输出SRT文件的完整路径。
#     """
#
#     # 创建输出目录，如果它不存在
#     if not os.path.exists(output_dir):
#         os.makedirs(output_dir)
#
#     # 确保输出文件名有.srt后缀
#     if not output_srt_file.endswith('.srt'):
#         output_srt_file += '.srt'
#
#     # 初始化当前时间
#     current_time = 1.000  # 初始时间
#
#     # 打开SRT文件进行写入
#     with open(output_srt_file, 'w', encoding='utf-8') as srt_file:
#         srt_index = 1
#
#         # 获取所有符合条件的子目录，并按索引排序
#         sub_dirs = [d for d in os.listdir(base_dir) if d.startswith('paragraph_')]
#         sub_dirs.sort(key=lambda x: int(re.search(r'\d+', x).group()))
#         # 遍历所有子目录
#         for sub_dir in sub_dirs:
#             sub_dir_path = os.path.join(base_dir, sub_dir)
#
#             # 查找所有的.md和.mp3文件
#             files = [f for f in os.listdir(sub_dir_path) if f.endswith('.md') or f.endswith('.mp3')]
#             md_files = [f for f in files if f.endswith('.md')]
#
#             # 按照index1和index2排序.md文件
#             md_files.sort(key=lambda x: int(x.split('_')[1].split('.')[0]))
#             # 处理每个.md文件
#             for md_file in md_files:
#                 md_file_path = os.path.join(sub_dir_path, md_file)
#                 mp3_file_path = os.path.splitext(md_file_path)[0] + '.mp3'
#
#                 # 确保对应的.mp3文件存在
#                 if os.path.exists(mp3_file_path):
#                     # 读取.md文件内容
#                     with open(md_file_path, 'r', encoding='utf-8') as f:
#                         text = f.read().strip()
#
#                     # 获取.mp3文件时长
#                     duration = get_audio_duration(mp3_file_path)
#
#                     # 生成SRT格式的字幕行
#                     start_time_str = format_time(current_time)
#                     end_time_str = format_time(current_time + duration)
#                     srt_line = create_srt_line(srt_index, start_time_str, end_time_str, text)
#
#                     # 写入SRT文件
#                     srt_file.write(srt_line)
#
#                     # 更新当前时间
#                     current_time += duration + 0.3  # 加上0.5秒以避免时间重叠
#
#                     srt_index += 1
#                 else:
#                     print(f"No corresponding MP3 file found for {md_file}")
#
#     print("SRT file generated successfully.")

def generate_srt_from_audio(base_dir: str, output_dir: str) -> None:
    """
    从指定目录下的音频文件夹生成SRT字幕文件。

    :param base_dir: 包含音频文件夹的根目录。
    :param output_dir: 输出SRT文件的目录。
    """

    # 创建输出目录，如果它不存在
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 获取所有符合条件的子目录，并按索引排序
    sub_dirs = [d for d in os.listdir(base_dir) if d.startswith('paragraph_')]
    sub_dirs.sort(key=lambda x: int(re.search(r'\d+', x).group()))



    # 遍历所有子目录
    for sub_dir in sub_dirs:
        sub_dir_path = os.path.join(base_dir, sub_dir)
        slide_number = re.search(r'\d+', sub_dir).group()
        output_srt_file = os.path.join(output_dir, f"slide_{slide_number}.srt")

        # 打开SRT文件进行写入
        with open(output_srt_file, 'w', encoding='utf-8') as srt_file:

            # 初始化当前时间
            current_time = 0.000  # 初始时间
            srt_index = 1
            # 查找所有的.md和.mp3文件
            files = [f for f in os.listdir(sub_dir_path) if f.endswith('.md') or f.endswith('.mp3')]
            md_files = [f for f in files if f.endswith('.md')]

            # 按照index1和index2排序.md文件
            md_files.sort(key=lambda x: int(x.split('_')[1].split('.')[0]))

            # 处理每个.md文件
            for md_file in md_files:
                md_file_path = os.path.join(sub_dir_path, md_file)
                mp3_file_path = os.path.splitext(md_file_path)[0] + '.mp3'

                # 确保对应的.mp3文件存在
                if os.path.exists(mp3_file_path):
                    # 读取.md文件内容
                    with open(md_file_path, 'r', encoding='utf-8') as f:
                        text = f.read().strip()

                    # 获取.mp3文件时长
                    duration = get_audio_duration(mp3_file_path)

                    # 生成SRT格式的字幕行
                    start_time_str = format_time(current_time)
                    end_time_str = format_time(current_time + duration)
                    srt_line = create_srt_line(srt_index, start_time_str, end_time_str, text)

                    # 写入SRT文件
                    srt_file.write(srt_line)

                    # 更新当前时间
                    current_time += duration + 0.3  # 加上0.3秒以避免时间重叠

                    srt_index += 1
                else:
                    print(f"No corresponding MP3 file found for {md_file}")

        print(f"SRT file generated successfully: {output_srt_file}")


def synthesize_md_to_speech(base_directory,voice_type="male"):
    """
    识别指定目录下的所有.md文件，读取其内容并使用DashScope API将其转换为语音，
    保存为同名.mp3文件在同一目录下。

    参数:
    base_directory (str): 包含.md文件的顶层目录路径。
    """
    # 确保环境变量中存在DashScope API密钥
    if 'DASHSCOPE_API_KEY' not in os.environ:
        raise ValueError("DashScope API key must be set in the environment variables.")

    if voice_type == "female":
        voice = "longxiaochun"
    else:
        voice = "longcheng"

    # 遍历指定目录及其子目录
    for root, dirs, files in os.walk(base_directory):
        for file in files:
            if file.endswith('.md'):
                # 构建完整文件路径
                md_file_path = os.path.join(root, file)

                # 读取.md文件内容
                with open(md_file_path, 'r', encoding='utf-8') as f:
                    text = f.read()

                # 初始化语音合成器
                speech_synthesizer = SpeechSynthesizer(model='cosyvoice-v1', voice=voice)

                # 合成语音
                audio_data = speech_synthesizer.call(text)

                # 构建输出.mp3文件路径
                mp3_file_path = os.path.splitext(md_file_path)[0] + '.mp3'

                # 保存音频到文件
                with open(mp3_file_path, 'wb') as f:
                    f.write(audio_data)

                print(f'Synthesized text from file "{md_file_path}" to file: {mp3_file_path}')


def calculate_audio_durations(directory):
    """
    计算指定目录下每个 mp3 文件的持续时间（以秒为单位）。

    参数:
        directory (str): 需要扫描的根目录路径。

    返回:
        list: 每个 mp3 文件持续时间（秒）的列表。
    """
    # 初始化结果列表
    durations = []
    # 遍历目录下的所有文件并按文件名排序
    pattern = r'^slide_(\d+)\.mp3$'
    image_files = [
        entry.path
        for entry in os.scandir(directory)
        if entry.name.endswith(".mp3") and re.match(pattern, entry.name)
    ]
    image_files = sorted(image_files, key=lambda x: int(re.match(pattern, os.path.basename(x)).group(1)))

    # 遍历排序后的文件列表
    for file in image_files:
        # 加载 mp3 文件并计算持续时间
        audio = AudioSegment.from_mp3(file)
        duration_seconds = len(audio) / 1000.0
        durations.append(duration_seconds)
        print(f"文件名: {os.path.basename(file)}, 持续时间: {duration_seconds} 秒")

    return durations

